package com.california.pay.socket;

import com.alibaba.fastjson.JSON;
import com.bwton.socket.skeleton.AbstractProviderProcessor;
import com.bwton.socket.transport.call.Request;
import com.bwton.socket.transport.call.Response;
import com.bwton.socket.transport.call.SocketResponse;
import com.california.pay.common.trace.TraceThreadLocal;
import com.california.pay.common.utils.MD5Sign;
import com.california.pay.config.CommonConstants;
import com.california.pay.config.CommonErrors;
import com.california.pay.service.TerminalLoginService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Sets;
import org.slf4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * socket controller 适配器类
 */
@Slf4j
public class SocketServerProcessorAdapter extends AbstractProviderProcessor implements InitializingBean {

    @Autowired
    protected TerminalLoginService loginService;

    private Set<String> NOT_NEED_SIGN_COMMAND_CODES = Sets.newHashSet();

    @Override
    public Response doHandle(Request request, Response response) {
        String simpleClassName = this.getClass().getSimpleName();
        initTraceId(simpleClassName + "#doHandle#");
        return null;
    }

    @Override
    public void printRequestInfo(Request request) {
    }

    @Override
    public Response createResponse(Request request) {
        return new SocketResponse(request, new TransSocketMessage(), request.getRemoteIp());
    }

    @Override
    public void printResponseInfo(Response response) {
    }

    public Logger getLogger() {
        return log;
    }

    @Override
    public Response encodeErrResponse(Exception e, Request request, Response response) {
        // 异常统一处理
        return null;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        NOT_NEED_SIGN_COMMAND_CODES.add("B1");
        NOT_NEED_SIGN_COMMAND_CODES.add("B0");
    }

    /**
     * 生成返回业务字段
     */
    public void buildBizResponse(String returnCode, Map<String, String> rspMap,
                                 TransSocketMessage reqMessage, Response response) {
        TransSocketMessage rspMessage = response.getValue();
        String sessionId = reqMessage.getSessionId();

        rspMessage.setAppId(reqMessage.getAppId());
        rspMessage.setVersion(reqMessage.getVersion());
        rspMessage.setSessionId(sessionId);
        rspMessage.setSeq(reqMessage.getSeq());
        rspMessage.setCommandCode(reqMessage.getCommandCode());
        rspMessage.setTimestamp(System.currentTimeMillis() + "");
        rspMessage.setReturnCode(returnCode);
        rspMessage.setSignMethod(reqMessage.getSignMethod());

        if (rspMap == null) {
            rspMap = new HashMap<>(4);
        }

        String message = JSON.toJSONString(rspMap);
        rspMessage.setMessage(message);
        String originBody = rspMessage.getOriginBody();

        String commandCode = reqMessage.getCommandCode();
        String sign = buildAckSign(originBody, rspMap, commandCode, rspMessage);

        String socketBody = originBody + "&signature=" + sign + CommonConstants.TAIL_END;
        rspMessage.setSocketBody(socketBody);
    }

    private String buildAckSign(String originBody, Map<String, String> rspMap, String commandCode, TransSocketMessage rspMessage) {
        String sign = "";
        if (!NOT_NEED_SIGN_COMMAND_CODES.contains(commandCode)) {
            String clientId = rspMap.get("clientId");
            String appkey = null;
            try {
                appkey = loginService.getAppKey(clientId);
            } catch (Exception e) {
                log.error("获取appkey异常, message=" + e.getMessage(), e);
                rspMessage.setReturnCode(CommonErrors.SIGNATURE_VERIFY_FAIL.getCode());
            }

            String signBody = originBody + "appKey=" + appkey;
            sign = MD5Sign.md5(signBody);
        }

        rspMessage.setSignature(sign);
        return sign;
    }

    protected void initTraceId(String tip) {
        String traceId = TraceThreadLocal.getTraceId();

        if (StringUtils.isBlank(traceId)) {
            traceId = tip + RandomUtils.nextInt();
            TraceThreadLocal.setTraceId(traceId);
        }

    }

}
